import { downloadFile } from '@/utils/file';
import { useFileSize } from '@/utils/hooks';
import request from '@/utils/request';
import { generateUuid, getUserIdentity } from '@/utils/utils';
import { Button, message, Upload } from 'antd';
import type { RcFile } from 'antd/lib/upload';
import type { UploadFile } from 'antd/lib/upload/interface';
import { isString } from 'lodash';
import React, { useCallback, useEffect, useState } from 'react';

const data = {
  tempFile: true,
  recTypeId: 0,
  recId: 0,
  subRecTypeId: 0,
  subRecId: 0,
};

const action = '/fwFile/file/upload.api';

export interface File extends UploadFile {
  id: number;
  virtureId: string;
}

export interface FileUploadProps {
  value: File[]; // 文件列表
  onChange: (files: File[]) => void; //上传或删除回调
  maxLength?: number; //最大上传文件个数
  editable?: boolean; //是否可以上传文件，删除文件
  buttonName?: string; //按钮名称
  uploadParams?: any; //上传接口的额外参数
  disabled?: boolean; // 禁用
}

const querying = new Set<string>();

const fileHouse = new Map<number, File>();

const FileUpload = (props: FileUploadProps) => {
  const { onChange, value, maxLength, editable = true, disabled, uploadParams = {}, ...restProps } = props;

  const extraHeader = getUserIdentity();

  const [buttomname, setButtomname] = useState('上传附件');
  useEffect(() => {
    if (props.buttonName) {
      setButtomname(props.buttonName);
    }
  }, []);

  const [name, setname] = useState(); // 文件上传名字
  const [files, setfiles] = useState([] as File[]);
  // 上传大小限制
  const [UPLOAD_FILE_SIZE, BEYOND_THE_HINT] = useFileSize();
  const [queryCount, setqueryCount] = useState(0);

  const queryFileInfo = useCallback((ids: number[]) => {
    const key = ids.join(',');
    if (querying.has(key)) return;
    querying.add(key);
    request
      .post('/gmetaBiz/getFileAndPictureInfo', {
        data: {
          ids,
        },
      })
      .then((data: File[]) => {
        ids.forEach((id) => {
          const item = data.find((item) => item.id === id);
          if (item) {
            // 文件还存在
            fileHouse.set(id, item);
          } else {
            fileHouse.set(id, { virtureId: '-1' } as File);
          }
        });
        setqueryCount((count) => count + 1);
        querying.delete(key);
      });
  }, []);

  const mergeValueToFiles = useCallback((value) => {
    const files = value
      .slice(0, maxLength)
      .filter((item) => !isString(item) && item.virtureId !== '-1')
      .map((file) => {
        const houseFile = fileHouse.get(file.id);
        const mergeFile = { ...file, uid: file.uid || generateUuid(), status: file.status || undefined };
        if (houseFile) {
          return { ...mergeFile, ...houseFile, status: 'done' };
        }
        return mergeFile;
      });
    const noNameFile = files.filter((file) => !file.name);
    if (noNameFile.length) {
      queryFileInfo(noNameFile.map((item) => item.id));
    }
    return files as File[];
  }, []);

  const beforeUpload = useCallback((file: RcFile, fileList: RcFile[]) => {
    const { name: n, size } = file;
    if (size > UPLOAD_FILE_SIZE) {
      message.warning(BEYOND_THE_HINT);
      return false;
    }
    setname(n);
    return true;
  }, []);

  const onFileChange = useCallback(
    ({ file, fileList, event }) => {
      let newFiles = fileList;
      if (file.status === 'done' && file.response.state === 'success') {
        // 上传成功
        message.success(tr('上传成功'));
        const { id, fileName: name, virtureId } = file.response.data[0];
        newFiles = [...fileList.slice(0, -1), { ...file, id, virtureId, name }];
      }
      onChange(newFiles);
      setfiles(newFiles);
    },
    [onChange],
  );

  //文件下载
  const onFileDownload = useCallback((_file) => {
    const { id, name } = _file;
    downloadFile({ id, fileName: name });
  }, []);

  useEffect(() => {
    const arr1 = _.map(files, 'id').sort();
    const arr2 = _.map(mergeValueToFiles(value), 'id').sort();
    if (arr1.join('') !== arr2.join('')) {
      setfiles(mergeValueToFiles(value));
    }
  }, [value]);

  useEffect(() => {
    const files = mergeValueToFiles(value);
    setfiles(files);
    onChange(files);
  }, [queryCount]);

  return (
    <Upload
      action={action}
      beforeUpload={beforeUpload}
      name={name}
      data={{
        ...data,
        ...uploadParams,
      }}
      headers={extraHeader}
      onChange={onFileChange}
      fileList={files}
      onDownload={onFileDownload}
      showUploadList={{ showDownloadIcon: true, showRemoveIcon: editable }}
      disabled={disabled}
      {...restProps}
    >
      {files.length < maxLength && editable && (
        <Button size="small" disabled={disabled} icon="upload">
          {buttomname}
        </Button>
      )}
    </Upload>
  );
};

FileUpload.defaultProps = {
  onChange: () => {},
  value: [],
  maxLength: 5,
};

export default FileUpload;
